11. JWT

  • JWT官网

  • 是一种使用Json格式的信息作为认证信息的交换方式

  • JWT是一种安全标准, 即具体实现可能好多种,或者可以把他理解成一种协议

  • 基本思路就是用户提供用户名和密码给认证服务器,服务器验证用户提交信息的合法性;

  • 如果验证成功,会产生并返回一个Token(令牌),用户可以使用这个token访问服务器上受保护的资源。

  • JWT 的目的不是为了隐藏或者保密数据

  • 在数据传输过程中,使用签名防止中途篡改数据

  • 认证过程

    • 依然是用户登录系统
    • 服务端验证,将认证信息通过指定的算法(例如HS256)进行加密,例如对用户名和用户所属角色进行加密,加密私钥是保存在服务器端的,将加密后的结果发送给客户端,加密的字符串格式为三个”.” 分隔的字符串 Token,分别对应头部、载荷与签名,头部和载荷都可以通过 base64 解码出来,签名部分不可以;
    • 客户端拿到返回的 Token,存储到 local storage 或本地数据库;
    • 下次客户端再次发起请求,将 Token 附加到 header 中;
    • 服务端获取 header 中的 Token ,通过相同的算法对 Token 中的用户名和所属角色进行相同的加密验证,如果验证结果相同,则说明这个请求是正常的,没有被篡改。这个过程可以完全不涉及到查询 Redis 或其他存储;
  • JWT是由三部分构成(用.分隔),将这三段信息文本用链接构成了JWT字符串

    • 形如

        xxxxx.yyyyy.zzzzz
      
    • 第一部分:头部(header)

      • JWT的头部承载的两部分信息:

      • 例如

          {
               'typ':'JWT', //声明类型,这里是jwt
               'alg':'HS256'  //声明加密的算法,通常直接使用HMAC SHA256或RSA
          }
        
      • Header部分的JSON被Base64Url编码,形成JWT的第一部分。

      • 例如

          eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
        
    • 第二部分:载荷(payload,该token里携带的有效信息。比如用户id、名字、年龄等等)

      • 这里放声明内容,可以说就是存放沟通讯息的地方,在定义上有3种声明(Claims):

        • Registered claims(注册声明): 这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行者),exp(到期时间),sub(主题),aud(受众)等。

        • Public claims(公开声明): 这些可以由使用JWT的人员随意定义。 但为避免冲突,应在IANA JSON Web令牌注册表中定义它们, 或将其定义为包含防冲突命名空间的URI。

        • Private claims(私有声明): 这些是为了同意使用它们但是既没有登记,也没有公开声明的各方之间共享信息,而创建的定制声明。

        • 例如:

           {
             "sub": "1234567890",
             "name": "Demo",
             "admin": true
           }
          
        • Playload部分的JSON被Base64Url编码,形成JWT的第二部分。

    • 第三部分:签名(signature)

      • 第三部分signature用来验证发送请求者身份,由前两部分加密形成。

      • 要创建签名部分,您必须采用编码标头,编码有效载荷,秘钥,标头中指定的算法并签名。

      • 例如: 使用HMAC SHA256算法,签名将按照以下方式创建:

          HMACSHA256(
            base64UrlEncode(header) + "." +
            base64UrlEncode(payload) + "." +
            secret)